///************************************************************************
/// <copyrigth>2018-2019 Corporation.All Rights Reserved</copyrigth>
/// <author>tangyingzhong</author>
/// <contact>tangyz114987@outlook.com</contact>
/// <version>v1.0.0</version>
/// <describe>
/// It is a soft video decoder
///</describe>
/// <date>2021/6/26</date>
///***********************************************************************
#ifndef VIDEOSOFTDECODER_H
#define VIDEOSOFTDECODER_H

extern "C" {
#include <libavutil/frame.h>
#include <libavutil/avutil.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/common.h>
#include <libavutil/hwcontext.h>
#include <libavutil/imgutils.h>
}
#include "IVideoSoftDecoder.h"

class VideoSoftDecoder :public IVideoSoftDecoder
{
public:
	// Construct the VideoSoftDecoder
	VideoSoftDecoder();

	// Detructe the VideoSoftDecoder
	virtual ~VideoSoftDecoder();

private:
	// Forbid the copy VideoSoftDecoder
	VideoSoftDecoder(const VideoSoftDecoder& other) {	};

	// Forbid the assigment of VideoSoftDecoder
	VideoSoftDecoder& operator=(const VideoSoftDecoder& other) { return *this; };

public:
	// Init the decoder
	virtual bool Init(VideoTypeEnum eVideoType);

	// Excute the decoding
	virtual bool Excute(uint8_t* pSrcData,
		int iSrcSize,
		uint8_t* pDst,
		int& iDstSize,
		int& iFrameWidth,
		int& iFrameHeight);

	// Flush the decode at the last frame decoding
	virtual void Flush();

private:
	// Initialize the decoder
	void Initialize();

	// Destory the decoder
	void Destory();

	// Init the decoder
	bool InitDecoder(AVCodecContext* pAvctx, AVCodec* pDecoder);

	// Release the decoder
	void ReleaseDecoder();

	// Decode the packet
	void Decode(AVCodecContext* pAvctx, AVPacket* pPacket, AVFrame* pFrame);

private:
	// Get the DecCodecCtx
	inline AVCodecContext* GetDecCodecCtx() const
	{
		return m_pDecCodecCtx;
	}

	// Set the DecCodecCtx
	inline void SetDecCodecCtx(AVCodecContext* pDecCodecCtx)
	{
		m_pDecCodecCtx = pDecCodecCtx;
	}

	// Get the ParserCtx
	inline AVCodecParserContext* GetParserCtx() const
	{
		return m_pParserCtx;
	}

	// Set the ParserCtx
	inline void SetParserCtx(AVCodecParserContext* pParserCtx)
	{
		m_pParserCtx = pParserCtx;
	}

	// Get the IsHaveInitDecoder
	inline bool GetIsHaveInitDecoder() const
	{
		return m_bIsHaveInitDecoder;
	}

	// Set the IsHaveInitDecoder
	inline void SetIsHaveInitDecoder(bool bIsHaveInitDecoder)
	{
		m_bIsHaveInitDecoder = bIsHaveInitDecoder;
	}

	// Get the disposed status
	inline bool GetDisposed() const
	{
		return m_bDisposed;
	}

	// Set the disposed status
	inline void SetDisposed(bool bDisposed)
	{
		m_bDisposed = bDisposed;
	}

private:
	// Decode context
	AVCodecContext* m_pDecCodecCtx;

	// Parser context
	AVCodecParserContext* m_pParserCtx;
	
	// Is init the decoder
	bool m_bIsHaveInitDecoder;

	// Disposed status
	bool m_bDisposed;
};

#endif // VIDEOSOFTDECODER_H
